home *** CD-ROM | disk | FTP | other *** search
- /*
- * brow.c - file browser, virtual display output
- * Bob Bybee, 3/22/91
- */
- #include <ssdef.h>
- #include <stdio.h>
- #include <descrip.h>
- #include <smgdef.h>
- #include <stat.h>
- #include <time.h>
- #include "vaxkeys.h"
-
- int kb_id, pb_id, output_device, pb_rows, pb_cols;
- int top_disp_id, bot_disp_id, main_disp_id;
- int vid_attr, main_size;
- int one = 1, two = 2, ins_dir;
- int top_line = 0;
- int tabsize = 8;
- int found_line = -1;
- char ftimebuf[80];
- FILE *fp;
- char filename[80];
-
- #define INPUT_BUFSIZE 60
- char inputbuf[INPUT_BUFSIZE + 1];
- char searchbuf[INPUT_BUFSIZE + 1];
- int input_bufsize = INPUT_BUFSIZE;
- int inputlen, searchlen;
-
- #define MAX_LINES 10000
- #define MAX_LINE_LENGTH 150
- char *pointers[MAX_LINES];
- int lastline;
-
-
- /* prototypes
- */
- void help_info( void );
- void repaint_page( void );
- void show_lineno( void );
- void bottom_line( char *msg );
- void get_line( int lineno, char *buf );
- void testret( int where, int ret );
- int getkey( void );
- void getline( char *prompt );
- void string_to_des( char *buf, struct dsc$descriptor *dp );
- void snuff_nl( char *buf );
- void filetime( FILE *fp, char *buf );
- void tabex( char *buf );
- void get_pointers( void );
- void strupr( char *s );
-
- int main( int argc, char **argv )
- {
- int c, i = 0, ret, row, col, how_far_in, how_far_down;
- int found_it, rendition, first_search, case_insens = 0;
- struct dsc$descriptor des;
- char buf[MAX_LINE_LENGTH], orig_buf[MAX_LINE_LENGTH], *p;
-
- --argc, ++argv;
- if (argc != 1)
- {
- printf("Usage: brow <filename>\n");
- exit(1);
- }
-
- if ((fp = fopen(*argv, "r")) == NULL)
- {
- printf("Can't open file: %s\n", *argv);
- exit(1);
- }
-
- filetime(fp, ftimebuf);
- strcpy(filename, *argv);
- filename[sizeof(filename) - 1] = '\0';
- get_pointers();
-
- testret(1, SMG$CREATE_VIRTUAL_KEYBOARD(&kb_id));
- testret(2, SMG$CREATE_PASTEBOARD(&pb_id,
- NULL, &pb_rows, &pb_cols));
- vid_attr = SMG$M_REVERSE;
- testret(3, SMG$CREATE_VIRTUAL_DISPLAY(&one, &pb_cols,
- &top_disp_id, 0, &vid_attr));
- testret(4, SMG$CREATE_VIRTUAL_DISPLAY(&one, &pb_cols,
- &bot_disp_id, 0, &vid_attr));
- vid_attr = 0;
- main_size = pb_rows - 2;
- testret(5, SMG$CREATE_VIRTUAL_DISPLAY(&main_size, &pb_cols,
- &main_disp_id, 0, &vid_attr));
- testret(6, SMG$PASTE_VIRTUAL_DISPLAY(&top_disp_id,
- &pb_id, &one, &one));
- testret(7, SMG$PASTE_VIRTUAL_DISPLAY(&bot_disp_id,
- &pb_id, &pb_rows, &one));
- testret(8, SMG$PASTE_VIRTUAL_DISPLAY(&main_disp_id,
- &pb_id, &two, &one));
-
- top_line = 0;
- repaint_page();
- while (1)
- {
- c = getkey();
- switch (c)
- {
- case '?':
- help_info();
- getkey();
- repaint_page();
- break;
-
- case DOWN_KEY:
- case 'D':
- case 'd':
- if (top_line + main_size - 1 < lastline)
- {
- ++top_line;
- strcpy(buf, pointers[top_line + main_size - 1]);
- tabex(buf);
- string_to_des(buf, &des);
- ins_dir = SMG$M_UP;
- testret(10, SMG$INSERT_LINE(&main_disp_id, &main_size,
- &des, &ins_dir));
- show_lineno();
- }
- break;
-
- case NEXT_SCREEN_KEY:
- case 'N':
- case 'n':
- case 'N' - '@':
- top_line += main_size - 1;
- repaint_page();
- break;
-
- case UP_KEY:
- case 'U':
- case 'u':
- if (top_line > 0)
- {
- --top_line;
- strcpy(buf, pointers[top_line]);
- tabex(buf);
- string_to_des(buf, &des);
- ins_dir = SMG$M_DOWN;
- testret(10, SMG$INSERT_LINE(&main_disp_id, &one,
- &des, &ins_dir));
- show_lineno();
- }
- break;
-
- case PREV_SCREEN_KEY:
- case 'P':
- case 'p':
- case 'P' - '@':
- top_line -= main_size - 1;
- repaint_page();
- break;
-
- case 'H':
- case 'h':
- case 'H' - '@':
- top_line = 0;
- repaint_page();
- break;
-
- case 'E':
- case 'e':
- case 'E' - '@':
- top_line = lastline - (main_size - 1);
- repaint_page();
- break;
-
- case 'L' - '@':
- testret(15, SMG$REPAINT_SCREEN(&pb_id));
- break;
-
- case '#':
- getline("Go to line: ");
- if (sscanf(inputbuf, "%d", &top_line) == 1)
- {
- --top_line; /* make it 0-based */
- repaint_page();
- }
- break;
-
- case 'I' - '@':
- getline("New tab size: ");
- if (sscanf(inputbuf, "%d", &tabsize) == 1)
- repaint_page();
- break;
-
-
- case PF3_KEY:
- if (found_line < 0)
- bottom_line("No previous search string.");
- else
- {
- first_search = found_line + 1;
- goto continue_search;
- }
- break;
-
- case '\\':
- case_insens = 1;
- goto ask_search;
-
- case '/':
- case FIND_KEY:
- case_insens = 0;
-
- ask_search:
- getline("Search for: ");
- if (inputlen == 0)
- break;
- strcpy(searchbuf, inputbuf);
- if (case_insens)
- strupr(searchbuf);
- searchlen = inputlen;
- first_search = top_line;
-
- continue_search:
- found_it = 0;
- for (i = first_search; !found_it && i <= lastline; ++i)
- {
- strcpy(buf, pointers[i]);
- tabex(buf);
- if (case_insens)
- {
- strcpy(orig_buf, buf);
- strupr(buf);
- }
-
- if ((p = strstr(buf, searchbuf)) != NULL)
- {
- /* found it. center the display on that string.
- * make how_far_in, how_far_down the 1-based
- * screen coords of the string on the screen.
- */
- how_far_in = p - buf + 1;
- top_line = i - main_size / 2;
- repaint_page();
- how_far_down = i - top_line + 1;
- rendition = SMG$M_REVERSE;
-
- if (case_insens)
- strcpy(buf, orig_buf); /* replace orig buffer */
-
- p[searchlen] = '\0';
- string_to_des(p, &des);
- testret(14, SMG$PUT_CHARS(&main_disp_id, &des,
- &how_far_down, &how_far_in,
- 0, &rendition));
- show_lineno(); /* move cursor to bottom line */
- found_it = 1;
- found_line = i;
- }
- }
- if (!found_it)
- bottom_line("Not found.");
- break;
-
- case 'Q':
- case 'q':
- case 'Q' - '@':
- case 'X':
- case 'x':
- case 'X' - '@':
- show_lineno(); /* put cursor on bottom line */
- printf("\n\n");
- exit(0);
- break;
-
- default:
- break;
- }
- }
-
- return (1);
- }
-
-
- /*
- * Display help-screen.
- */
- void help_info( void )
- {
- int i, y;
- char **pp;
- struct dsc$descriptor des;
-
- static char *help_msgs[] =
- {
- " ",
- " BROWSE version 1.0 3/26/91",
- " ",
- " H: home (top of file) /, FIND: locate text string",
- " E: end (bottom of file) \\: locate (case insensitive)",
- " U, up-arrow: up one line PF3: continue search",
- " P, prev-screen: up one screen",
- " D, down-arrow: down one line",
- " N, next-screen: down one screen",
- " ",
- " #: go to a line # ^L: repaint screen",
- " TAB: change tab-size setting",
- " Q, X: quit",
- " ",
- " hit any key to continue...",
- NULL
- };
-
- /* batch up the following stuff.
- */
- SMG$BEGIN_PASTEBOARD_UPDATE(&pb_id);
-
- SMG$SET_CURSOR_ABS(&main_disp_id, &one, &one);
- for (pp = help_msgs, y = 1, i = 0; i < main_size; ++i, ++y)
- {
- if (*pp != NULL)
- {
- string_to_des(*pp, &des);
- ++pp;
- }
- else
- string_to_des(" ", &des);
-
- testret(11, SMG$PUT_LINE(&main_disp_id, &des));
- }
-
- /* end batching.
- */
- SMG$END_PASTEBOARD_UPDATE(&pb_id);
- }
-
-
- /*
- * Get an input line, prompting on the bottom line of the screen.
- * Put result in inputbuf, length in inputlen.
- */
- void getline( char *prompt )
- {
- struct dsc$descriptor result_des, prompt_des;
- int modifiers = 0;
- short result_len;
-
- string_to_des(prompt, &prompt_des);
-
- result_des.dsc$w_length = INPUT_BUFSIZE;
- result_des.dsc$a_pointer = inputbuf;
- result_des.dsc$b_class = DSC$K_CLASS_S;
- result_des.dsc$b_dtype = DSC$K_DTYPE_T;
-
- SMG$READ_STRING(&kb_id,
- &result_des,
- &prompt_des,
- &input_bufsize,
- &modifiers,
- 0, /* timeout */
- 0, /* terminator set */
- &result_len,
- 0, /* word terminator code */
- &bot_disp_id);
-
- inputbuf[result_len] = '\0';
- inputlen = result_len;
- show_lineno(); /* fix the bottom line of the screen */
- }
-
-
- /*
- * Repaint the screen, given the current value of top_line.
- */
- void repaint_page( void )
- {
- int i, y, bot_line;
- struct dsc$descriptor des;
- char buf[MAX_LINE_LENGTH];
-
- /* sanity-check the top_line variable.
- */
- if (top_line + main_size - 1 > lastline)
- top_line = lastline - (main_size - 1);
- if (top_line < 0)
- top_line = 0;
-
- /* batch up the following stuff.
- */
- SMG$BEGIN_PASTEBOARD_UPDATE(&pb_id);
-
- /* label the top line with the file time/date.
- */
- sprintf(buf, " File: %s %s", filename, ftimebuf);
- string_to_des(buf, &des);
- testret(9, SMG$PUT_LINE(&top_disp_id, &des));
-
- SMG$SET_CURSOR_ABS(&main_disp_id, &one, &one);
-
- /* put N lines in the main viewing area
- */
- bot_line = top_line + main_size - 1;
- for (y = 1, i = top_line; i <= bot_line; ++i, ++y)
- {
- get_line(i, buf);
- string_to_des(buf, &des);
- testret(11, SMG$PUT_LINE(&main_disp_id, &des));
- }
-
- show_lineno();
-
- /* end batching, flush this update to the screen.
- */
- SMG$END_PASTEBOARD_UPDATE(&pb_id);
- }
-
-
- /*
- * Label the bottom line with current line # and max lines in file.
- */
- void show_lineno( void )
- {
- char buf[80];
- struct dsc$descriptor des;
- int last_shown;
-
- last_shown = top_line + main_size;
- if (last_shown > lastline + 1)
- last_shown = lastline + 1;
- sprintf(buf, " lines %5d - %5d (of %5d) BROWSE v1.0 ?=help",
- top_line + 1, last_shown, lastline + 1);
- string_to_des(buf, &des);
- testret(12, SMG$PUT_LINE(&bot_disp_id, &des));
- }
-
-
- /*
- * Put a message on bottom line of the screen.
- */
- void bottom_line( char *msg )
- {
- struct dsc$descriptor des;
-
- string_to_des(msg, &des);
- testret(12, SMG$PUT_LINE(&bot_disp_id, &des));
- }
-
-
- /*
- * Get the strings of all lines in the file.
- * Set lastline to the last used entry in pointers[].
- */
- void get_pointers( void )
- {
- char *p, buf[MAX_LINE_LENGTH];
-
- while (lastline < MAX_LINES && fgets(buf, MAX_LINE_LENGTH, fp) != NULL)
- {
- if ((p = malloc(strlen(buf) + 1)) == NULL)
- {
- printf("Out of memory!\n");
- exit(1);
- }
- strcpy(p, buf);
- pointers[lastline++] = p;
- }
-
- --lastline;
- }
-
-
- /*
- * Return the text corresponding to lineno of the file.
- * Tab-expand the text and put it in buf.
- */
- void get_line( int lineno, char *buf )
- {
- int i;
-
- /* if past EOF, return a blank line
- */
- if (lineno > lastline)
- {
- *buf = '\0';
- return;
- }
-
- strcpy(buf, pointers[lineno]);
- tabex(buf);
- }
-
-
- /*
- * Tab-expand a buffer, in place.
- */
- void tabex( char *buf )
- {
- char buf2[200], c;
- int i = 0, j = 0;
-
- while ((c = buf[i++]) != '\0' && c != '\n')
- {
- if (c == '\t')
- {
- do {
- buf2[j++] = ' ';
- } while (j % tabsize != 0);
- }
- else
- buf2[j++] = c;
- }
- buf2[j] = '\0';
- strcpy(buf, buf2);
- }
-
-
- /*
- * Test the return value from a system call,
- * error out if not success.
- */
- void testret( int where, int ret )
- {
- if (ret != SS$_NORMAL)
- {
- printf("Error: where= %d code= %d\n", where, ret);
- exit(0);
- }
- }
-
-
- /*
- * Get one keystroke from kb_id
- */
- int getkey( void )
- {
- short termcode;
-
- SMG$READ_KEYSTROKE(&kb_id, &termcode);
- return (termcode);
- }
-
-
- /*
- * install character string in a descriptor
- */
- void string_to_des( char *buf, struct dsc$descriptor *dp )
- {
- dp->dsc$w_length = strlen(buf);
- dp->dsc$a_pointer = buf;
- dp->dsc$b_class = DSC$K_CLASS_S;
- dp->dsc$b_dtype = DSC$K_DTYPE_T;
- }
-
-
- /*
- * Insert NUL at first control-char in a buffer.
- */
- void snuff_nl( char *buf )
- {
- while (*buf >= ' ')
- ++buf;
- *buf = '\0';
- }
-
-
- /*
- * Get file time/date into a string buffer.
- */
- void filetime( FILE *fp, char *buf )
- {
- int fd, r;
- time_t bintim;
- stat_t statbuf;
- struct dsc$descriptor des;
-
- des.dsc$w_length = 23;
- des.dsc$a_pointer = buf;
- des.dsc$b_class = DSC$K_CLASS_S;
- des.dsc$b_dtype = DSC$K_DTYPE_T;
-
- fd = fileno(fp);
- if ((r = fstat(fd, &statbuf)) != 0)
- {
- printf("fstat returned %d\n", r);
- exit(1);
- }
-
- bintim = statbuf.st_mtime;
- strcpy(buf, ctime(&bintim));
- snuff_nl(buf);
- }
-
-
- /*
- * Convert a string to upper case.
- */
- void strupr( char *s )
- {
- char c;
-
- while ((c = *s) != '\0')
- {
- if ('a' <= c && c <= 'z')
- *s -= 'a' - 'A';
- ++s;
- }
- }
-